﻿using System;
using System.Diagnostics;
using System.Resources;
using System.Windows;
using System.Windows.Markup;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using Jive.Resources;
using Windows.Devices.Geolocation;
using System.Linq;
using System.Threading;
using System.Windows.Threading;
using System.Collections.Generic;
using Microsoft.Phone.Notification;
using Jive.CustomControls;
using System.IO.IsolatedStorage;
using System.IO;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Jive.Network;
using GalaSoft.MvvmLight.Messaging;
using Jive.Helpers;
using Jive.Settings;
using Jive.ViewModels;
using Microsoft.Phone.Info;
using JmShared;
using Jive.User;

namespace Jive
{
    public partial class App : Application
    {
        /// <summary>
        /// Provides easy access to the root frame of the Phone Application.
        /// </summary>C:\Users\Ole\documents\visual studio 2012\Projects\Jive\Jive\Resources\
        /// <returns>The root frame of the Phone Application.</returns>
        private Thread _lockscreenThread;
        private DispatcherTimer _receiptTimer;
        private Dictionary<int, KeyValuePair<DateTime, ChatMessage>> _sentMessages;
        private object ReceiveEmoticonLockObject = new object();

        public static PhoneApplicationFrame RootFrame { get; private set; }
        public static NetworkConnection Connection { get; set; }

        
        public static int unreadMsgCount { get; set; }







        /// Constructor for the Application object.
        /// </summary>
        public App()
        {
            // Global handler for uncaught exceptions.
            UnhandledException += Application_UnhandledException;

            // Standard XAML initialization
            InitializeComponent();

            // Phone-specific initialization
            InitializePhoneApplication();

            // Language display initialization
            InitializeLanguage();
            // Show graphics profiling information while debugging.
            if (Debugger.IsAttached)
            {
                // Display the current frame rate counters.
                Application.Current.Host.Settings.EnableFrameRateCounter = true;

                // Show the areas of the app that are being redrawn in each frame.
                //Application.Current.Host.Settings.EnableRedrawRegions = true;

                // Enable non-production analysis visualization mode,
                // which shows areas of a page that are handed off to GPU with a colored overlay.
                //Application.Current.Host.Settings.EnableCacheVisualization = true;

                // Prevent the screen from turning off while under the debugger by disabling
                // the application's idle detection.
                // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run
                // and consume battery power when the user is not using the phone.
                PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
            }

            Messenger.Default.Register<Uri>(this, (u) => RootFrame.Navigate(u));

            _sentMessages = new Dictionary<int, KeyValuePair<DateTime, ChatMessage>>();
            AppSettings.AppSettingsInstance.PropertyChanged += AppSettings_PropertyChanged;
            Connection = new NetworkConnection(GetUniqueId());
            InitReceiptTimer();
            Connection.ChatMessageReceived += Connection_ChatMessageReceived;
            Connection.ChatMessageSendt += Connection_ChatMessageSendt;
            Connection.ChatReceiptReceived += Connection_ChatReceiptReceived;
            Connection.OnDisconnected += Connection_OnDisconnected;

            Connection.HostnameLookupSucceeded += Connection_HostnameLookupSucceeded;
            Connection.MessageQueueItemReceived += Connection_MessageQueueItemReceived;
        }

        void Connection_MessageQueueItemReceived(object sender, MessageQueueUpdateEventArgs e)
        {
            var viewModelLocator = (ViewModelLocator)Application.Current.Resources["Locator"];
            viewModelLocator.ViewModelMainPage.MessageQueueItemReceivedCommand.Execute(e);
        }

        void Connection_HostnameLookupSucceeded(object sender, HostnameLookupEventArgs e)
        {
            if (AppSettings.AppSettingsInstance.HostnameCache == null)
                AppSettings.AppSettingsInstance.HostnameCache = new Dictionary<string, string>();

            AppSettings.AppSettingsInstance.HostnameCache[AppSettings.AppSettingsInstance.ServerSetting] = e.IPAddress;
        }

        void Connection_OnDisconnected(object sender, EventArgs e)
        {

            if (Client.ClientInstance.IsLoggedIn)
            {
                if (Client.ClientInstance.CurrentUserInfo != null)
                    DisplayGroupMessage(Client.RedText, Client.ClientInstance.CurrentUserInfo.PrettyName + " has left the conversation!", MessageType.Logout, DateTime.Now);
            }
            Client.ClientInstance.IsLoggedIn = false;
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                var viewModelLocator = (ViewModelLocator)Application.Current.Resources["Locator"];
                viewModelLocator.ViewModelMainPage.RunOnNetworkDisconnect();
                viewModelLocator.ViewModelPrivateMessagePage.RunOnNetworkDisconnect();
                _receiptTimer.Stop();
            });
        }

        void Connection_ChatReceiptReceived(object sender, ChatReceiptEventArgs e)
        {
            AcknowledgeSendtMessageReceipt(e.Receipt.MessageID);
        }

        void Connection_ChatMessageSendt(object sender, ChatMessageEventArgs e)
        {
            ChatMessage msg = e.Message;
            if (msg.MessageType == MessageType.Message || msg.MessageType == MessageType.PM)
            {
                _sentMessages.Add(msg.MessageID.Value, new KeyValuePair<DateTime, ChatMessage>(DateTime.Now, msg));
            }
        }
        private void InitReceiptTimer()
        {
            _receiptTimer = new DispatcherTimer();
            _receiptTimer.Interval = new TimeSpan(0, 0, 3);
            _receiptTimer.Tick += _receiptTimer_Tick;
        }
        private void _receiptTimer_Tick(object sender, EventArgs e)
        {
            List<int> toRemove = new List<int>();
            foreach (var v in _sentMessages)
            {
                if (DateTime.Now.Subtract(v.Value.Key).TotalSeconds > 6)
                {
                    DisplayGroupMessage(Client.RedText, String.Format("Message response timeout. It is possible the message was not received: {0}", v.Value.Value.Message), MessageType.Error, DateTime.Now);
                    toRemove.Add(v.Key);
                }
            }
            foreach (int i in toRemove)
                _sentMessages.Remove(i);
        }
        private void AcknowledgeSendtMessageReceipt(int id)
        {
            this._sentMessages.Remove(id);
        }
        void Connection_ChatMessageReceived(object sender, ChatMessageEventArgs e)
        {
            ChatMessage msg = e.Message;

            if (Client.ClientInstance.ConnectedClients.ContainsKey(msg.SenderID))
                msg.Sender = Client.ClientInstance.ConnectedClients[msg.SenderID];
            switch (msg.MessageType)
            {
                case MessageType.LoginFailed:
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            Messenger.Default.Send("Wrong username or password.");
                        });
                        break;
                    }
                case MessageType.LoginSuccessful:
                    {
                        UserInfo user = StaticMethods.StringToObject<UserInfo>(msg.Message);
                        Client.ClientInstance.CurrentUserInfo = user;

                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            var viewModelLocator = (ViewModelLocator)Application.Current.Resources["Locator"];
                            viewModelLocator.ViewModelMainPage.RunOnNetworkConnect();
                            AddOrUpdateUsers(user);
                            _receiptTimer.Start();
                        });

                        _sentMessages = new Dictionary<int, KeyValuePair<DateTime, ChatMessage>>();

                        Client.ClientInstance.IsLoggedIn = true;

                        Thread t = new Thread(() =>
                        {
                            App.ResetTileCount();
                            App.RegisterPush(true, AppSettings.AppSettingsInstance.IsToastNotificationEnabledSetting);

                        }) { IsBackground = true };

                        t.Start();


                        //if (LoginSuccessful != null)
                        //    LoginSuccessful(this, null);
                        this.DisplayGroupMessage(Client.GreenText, "Login successful", msg.MessageType, msg.MessageRelayTime);

                        BroadcastEmoticons();

                        break;
                    }
                case MessageType.Authenticated:
                    {
                        UserInfo user = StaticMethods.StringToObject<UserInfo>(msg.Message);

                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            AddOrUpdateUsers(user);
                            if (Client.ClientInstance.ConnectedClients.Values.ToList().FindAll(x => x.UserName == user.UserName).Count == 1)
                                this.DisplayGroupMessage(Client.GreenText, user.PrettyName + " has been added to the conversation.", msg.MessageType, msg.MessageRelayTime);
                        });
                        BroadcastEmoticons();
                        break;
                    }
                case MessageType.Message:
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() =>this.DisplayGroupMessage(msg));
                        break;
                    }
                case MessageType.PM:
                    {
                        Deployment.Current.Dispatcher.BeginInvoke((Action)(() => ProcessPM(msg)));
                        break;
                    }
                case MessageType.Hello:
                    {
                        Deployment.Current.Dispatcher.BeginInvoke((Action)(() => this.AddOrUpdateUsers(StaticMethods.StringToObject<UserInfo[]>(msg.Message))));
                        break;
                    }
                case MessageType.UpdateUserInfo:
                    {
                        Deployment.Current.Dispatcher.BeginInvoke((Action)(() => this.AddOrUpdateUsers(StaticMethods.StringToObject<UserInfo>(msg.Message))));
                        break;
                    }
                case MessageType.Logout:
                    {
                       Deployment.Current.Dispatcher.BeginInvoke((Action)(() => RemoveUser(msg.Recipients)));
                        break;
                    }
                case MessageType.Busy:
                case MessageType.AFK:
                    {
                        UserInfo user = StaticMethods.StringToObject<UserInfo>(msg.Message);
                        Deployment.Current.Dispatcher.BeginInvoke(() => AddOrUpdateUsers(user));

                        break;
                    }
                case MessageType.BroadcastEmoticons:
                    {

                        ProcessCustomContactEmoticons(msg);
                        break;
                    }
                case MessageType.RequestingEmoticon:
                    {
                        if (!StaticSettings.IsWifiEnabled)
                            return;//don't transfer emoticon images without wifi

                        if (!StaticSettings.CustomEmoticons.ContainsKey(msg.Message))
                            break;
                        if (String.IsNullOrEmpty(StaticSettings.CustomEmoticons[msg.Message]))
                            break;
                        ContactEmoticon ce = new ContactEmoticon
                        {
                            KeyWord = msg.Message,
                            EmoticonByteArray = StaticMethods.LoadImageAsByteArray(StaticSettings.GetEmoticons(Client.ClientInstance.CurrentUserInfo.UserID, true, true)[msg.Message])
                        };
                        msg.Message = StaticMethods.ContactEmoticonToString(ce);
                        msg.MessageType = MessageType.SendingEmoticon;
                        //UserInfo receiver = msg.Sender;
                        msg.Recipients = new string[1];
                        msg.Recipients[0] = msg.SenderID;
                        msg.SenderID = Client.ClientInstance.CurrentUserInfo.UserID;
                        Connection.SendMessage(msg);
                        break;
                    }
                case MessageType.SendingEmoticon:
                    {
                        ReceiveEmoticon(msg);
                        break;
                    }
            }
        }
        private void DisplayGroupMessage(ChatMessage msg)
        {

                var viewModelLocator = (ViewModelLocator)Application.Current.Resources["Locator"];
                viewModelLocator.ViewModelMainPage.AddMessage(msg);

        }
        /// <summary>
        /// Broadcast your custom emoticons
        /// </summary>
        private void BroadcastEmoticons()
        {
            Connection.SendStatusMessage(MessageType.BroadcastEmoticons, StaticMethods.ListToString<string>(StaticSettings.CustomEmoticons.Keys.ToList()));
        }
        private void DisplayGroupMessage(UserInfo sender, string messageText, MessageType mt, DateTime timestamp)
        {
            ChatMessage msg = new ChatMessage
            {
                MessageType = mt,
                Message = messageText,
                SenderID = sender.UserID,
                Sender = sender,
                MessageRelayTime = timestamp
            };
            Deployment.Current.Dispatcher.BeginInvoke(() => DisplayGroupMessage(msg));

        }
        private void AddOrUpdateUsers(UserInfo user)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                var viewModelLocator = (ViewModelLocator)Application.Current.Resources["Locator"];
                viewModelLocator.ViewModelMainPage.AddOrUpdateContact(user);
            });
            //if (UserAddedOrUpdated != null)
            //    UserAddedOrUpdated(this, new UserAddedEventArgs(user));
        }
        private void AddOrUpdateUsers(UserInfo[] users)
        {
            foreach (UserInfo user in users)
            {
                AddOrUpdateUsers(user);
            }
        }
        private void RemoveUser(string[] users)
        {
            if (users == null)
                return;
            var viewModelLocator = (ViewModelLocator)Application.Current.Resources["Locator"];
            foreach (string user in users)
            {
                UserInfo u = null;
                if (Client.ClientInstance.ConnectedClients.TryGetValue(user, out u))
                {
                    if (user.Equals(Client.ClientInstance.CurrentUserInfo)) // don't remove our own connected user.
                        return;
                    Client.ClientInstance.ConnectedClients.Remove(u.UserID);
                    viewModelLocator.ViewModelMainPage.RemoveOfflineContact(u.UserName);
                }
                //if (UserRemoveRequest != null)
                //    UserRemoveRequest(this, new UserRemovedEventArgs(user));
            }
        }
        /// <summary>
        /// Process other users custom emoticons.
        /// </summary>
        /// <param name="message"></param>
        private void ProcessCustomContactEmoticons(ChatMessage message)
        {
            Debug.WriteLine("Processing custom contact emoticons");
            List<string> customEmoticons = StaticMethods.StringToList<string>(message.Message);
            if (AppSettings.AppSettingsInstance.CustomContactEmoticons == null)
                AppSettings.AppSettingsInstance.CustomContactEmoticons = new Dictionary<string, Dictionary<string, string>>();
            foreach (string str in customEmoticons)
            {

                lock (ReceiveEmoticonLockObject)
                {
                    if (!AppSettings.AppSettingsInstance.CustomContactEmoticons.ContainsKey(message.SenderID))
                    {
                        AppSettings.AppSettingsInstance.CustomContactEmoticons[message.SenderID] = new Dictionary<string, string>(); // List<Emoticons.ContactEmoticon>();
                    }
                }
                bool requestEmoticon = false;
                if (!AppSettings.AppSettingsInstance.CustomContactEmoticons[message.SenderID].ContainsKey(str))
                {
                    requestEmoticon = true;
                }
                else if (String.IsNullOrEmpty(AppSettings.AppSettingsInstance.CustomContactEmoticons[message.SenderID][str]) && StaticSettings.IsWifiEnabled) //don't request emoticons without wifi.
                    requestEmoticon = true;
                if (requestEmoticon)
                {
                    //save a reference to the emoticon in the library
                    lock (ReceiveEmoticonLockObject)
                    {
                        if (!AppSettings.AppSettingsInstance.CustomContactEmoticons[message.SenderID].ContainsKey(str))
                            AppSettings.AppSettingsInstance.CustomContactEmoticons[message.SenderID].Add(str, string.Empty); //new Emoticons.ContactEmoticon { KeyWord = str });
                    }
                    //Send a message to the user requesting the user send the emoticon so we can save it to disk
                    ChatMessage msg = new ChatMessage();
                    msg.MessageType = MessageType.RequestingEmoticon;
                    msg.Message = str;
                    //UserInfo receiver = message.Sender;
                    msg.SenderID = Client.ClientInstance.CurrentUserInfo.UserID;
                    msg.Recipients = new string[1];
                    msg.Recipients[0] = message.SenderID;
                    Connection.SendMessage(msg);
                    Debug.WriteLine(string.Format("Requesting emoticon for key {0}", str));
                    Thread.Sleep(300);
                }
                else
                    Debug.WriteLine(string.Format("Skipping emoticon request for key {0}", str));
            }
            lock (ReceiveEmoticonLockObject)
            {
                List<string> toRemove = new List<string>();
                if (AppSettings.AppSettingsInstance.CustomContactEmoticons.ContainsKey(message.SenderID))
                {
                    foreach (KeyValuePair<string, string> kvp in AppSettings.AppSettingsInstance.CustomContactEmoticons[message.SenderID])
                    {
                        if (!customEmoticons.Contains(kvp.Key))
                            toRemove.Add(kvp.Key);
                    }
                }
                foreach (string str in toRemove)
                {
                    AppSettings.AppSettingsInstance.CustomContactEmoticons[message.SenderID].Remove(str);
                    Debug.WriteLine(string.Format("Removed emoticon for user {0} and key {1}", message.SenderID, str));
                }
            }
        }

        /// <summary>
        /// Receives a custom contact emoticon as a chatmessage, saves it to disk and stores the reference.
        /// </summary>
        /// <param name="msg"></param>
        private void ReceiveEmoticon(ChatMessage msg)
        {
            UserInfo user = msg.Sender;

            ContactEmoticon ce = StaticMethods.StringToObject<ContactEmoticon>(msg.Message);
            Debug.WriteLine(string.Format("Received emoticon from {0} for key {1}", msg.SenderID, ce.KeyWord));
            if (String.IsNullOrEmpty(ce.KeyWord))
                return;

            IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
            string savePath = StaticSettings.CustomContactEmoticonFolder;
            if (!storage.DirectoryExists(savePath))
                storage.CreateDirectory(savePath);

            savePath = StaticMethods.CombinePath(savePath, "Icons_" + user.UserName);
            if (!storage.DirectoryExists(savePath))
                storage.CreateDirectory(savePath);

            savePath = StaticMethods.CombinePath(savePath, StaticMethods.FileNameFriendly(ce.KeyWord) + ce.Extension);
            try
            {
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {

                    BitmapImage b = new BitmapImage();
                    b.SetSource(new MemoryStream(ce.EmoticonByteArray));
                    StaticMethods.SaveToPng(b, savePath);

                    Debug.WriteLine(string.Format("Saved emoticon from {0} for key {1} to isolated storage", msg.SenderID, ce.KeyWord));
                });

            }
            catch (IOException err)
            {
                Messenger.Default.Send(String.Format("Error saving custom emoticon from {0} : ", user.UserName) + err.Message);
                return;
            }
            if (AppSettings.AppSettingsInstance.CustomContactEmoticons.ContainsKey(msg.SenderID))
            {
                Dictionary<string, string> cce = AppSettings.AppSettingsInstance.CustomContactEmoticons[msg.SenderID];

                if (cce.ContainsKey(ce.KeyWord))
                {
                    cce[ce.KeyWord] = savePath;
                    Debug.WriteLine(string.Format("Matched emoticon from {0} for key {1} to custom contact emoticon list", msg.SenderID, ce.KeyWord));
                }
            }
        }

        private void ProcessPM(ChatMessage msg)
        {
            UserInfo user = msg.Sender;
            if (!Client.ClientInstance.PrivateMessages.ContainsKey(user.UserName))
                Client.ClientInstance.PrivateMessages.Add(user.UserName, new List<ChatMessage>());
            Client.ClientInstance.PrivateMessages[user.UserName].Add(msg);

            var viewModelLocator = (ViewModelLocator)Application.Current.Resources["Locator"];

            if (viewModelLocator.ViewModelPrivateMessagePage != null
                && viewModelLocator.ViewModelPrivateMessagePage.PmTarget != null
                && viewModelLocator.ViewModelPrivateMessagePage.PmTarget.UserName == user.UserName)
            {
                viewModelLocator.ViewModelPrivateMessagePage.AddMessage(user, msg.Message, msg.MessageType, msg.MessageRelayTime);
            }
            else
            {
                viewModelLocator.ViewModelMainPage.IncrementContactUnreadPmCount(msg.Sender.UserName);
            }
        }
        void AppSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsLockscreenDisabledSetting")
                SetLockscreenState((bool)sender);
        }


        // Code to execute when the application is launching (eg, from Start)
        // This code will not execute when the application is reactivated
        private void Application_Launching(object sender, LaunchingEventArgs e)
        {

            //Thread t = new Thread(() =>
            //{
            //    foreach (KeyValuePair<string, string> kvp in StaticSettings.CustomEmoticons)
            //    {
            //        Deployment.Current.Dispatcher.BeginInvoke(() =>
            //            {
            //                BitmapImage i = StaticMethods.LoadBitmapImageFromIsolatedStorage(kvp.Value);
            //            });
            //    }

            //});
            //t.IsBackground = true;
            //t.Start();
        }

        // Code to execute when the application is activated (brought to foreground)
        // This code will not execute when the application is first launched
        private void Application_Activated(object sender, ActivatedEventArgs e)
        {

            if (_lockscreenThread != null && _lockscreenThread.IsAlive)
                _lockscreenThread.Abort();

            _lockscreenThread = new Thread(() =>
                {
                    try
                    {
                        Connection.SendStatusMessage(MessageType.UpdateDeviceStatus, StaticMethods.ObjectToString<DeviceInfo>(new DeviceInfo
                        {
                            IsActive = true,
                            IsTileEnabled = AppSettings.AppSettingsInstance.IsTileNotificationEnabledSetting,
                            IsToastEnabled = AppSettings.AppSettingsInstance.IsToastNotificationEnabledSetting,
                            StoreMessagesWhileOffline = AppSettings.AppSettingsInstance.StoreMessagesWhileOfflineSetting,
                            OfflineMessagesAgeLimit = AppSettings.AppSettingsInstance.OfflineMessageAgeLimitSetting,
                            OfflineMessagesCountLimit = AppSettings.AppSettingsInstance.OfflineMessageCountLimitSetting,
                            SendGroupPushWhileOffline = AppSettings.AppSettingsInstance.OfflinePmToastEnabledSetting,
                            SendPmPushWhileOffline = AppSettings.AppSettingsInstance.OfflineGroupToastEnabledSetting
                        }));

                        Thread.Sleep(2500);

                        if (Client.ClientInstance.IsLoggedIn)
                        {
                            ResetTileCount();
                        }
                    }
                    catch { }
                })
                {
                    Name = "ResetTileThread",
                    IsBackground = true
                };
            _lockscreenThread.Start();

            Debug.WriteLine(DateTime.Now.ToLongTimeString() + ": running in background = false");
        }

        // Code to execute when the application is deactivated (sent to background)
        // This code will not execute when the application is closing
        private void Application_Deactivated(object sender, DeactivatedEventArgs e)
        {
            //UpdateUiTimer.Stop();
            if (Client.ClientInstance.IsLoggedIn && Connection.MasterConnectionInfo.ConnectionState == NetworkCommsDotNet.ConnectionState.Established)
            {
                try
                {
                    Connection.SendStatusMessage(MessageType.ResetUnreadMessageCount, StaticMethods.ObjectToString<DeviceInfo>(new DeviceInfo
                    {
                        IsActive = false,
                        IsTileEnabled = AppSettings.AppSettingsInstance.IsTileNotificationEnabledSetting,
                        IsToastEnabled = AppSettings.AppSettingsInstance.IsToastNotificationEnabledSetting,
                        StoreMessagesWhileOffline = AppSettings.AppSettingsInstance.StoreMessagesWhileOfflineSetting,
                        OfflineMessagesAgeLimit = AppSettings.AppSettingsInstance.OfflineMessageAgeLimitSetting,
                        OfflineMessagesCountLimit = AppSettings.AppSettingsInstance.OfflineMessageCountLimitSetting,
                        SendGroupPushWhileOffline = AppSettings.AppSettingsInstance.OfflineGroupToastEnabledSetting,
                        SendPmPushWhileOffline = AppSettings.AppSettingsInstance.OfflinePmToastEnabledSetting
                    }));
                }
                catch { }
            }

        }

        // Code to execute when the application is closing (eg, user hit Back)
        // This code will not execute when the application is deactivated
        private void Application_Closing(object sender, ClosingEventArgs e)
        {
            if (Connection != null)
                Connection.SendStatusMessage(MessageType.Logout, string.Empty);
            if (AppSettings.AppSettingsInstance.CustomContactEmoticons != null)
            {
                Dictionary<string, Dictionary<string, string>> dic = new Dictionary<string, Dictionary<string, string>>();
                foreach (KeyValuePair<string, Dictionary<string, string>> kvp in AppSettings.AppSettingsInstance.CustomContactEmoticons)
                {
                    Dictionary<string, string> emoticons = new Dictionary<string, string>();
                    foreach (KeyValuePair<string, string> kvp2 in kvp.Value)
                    {
                        if (!String.IsNullOrEmpty(kvp2.Value))
                            emoticons.Add(kvp2.Key, kvp2.Value);
                    }
                    if (emoticons.Count > 0)
                    {
                        dic.Add(kvp.Key, emoticons);
                    }
                }
                AppSettings.AppSettingsInstance.CustomContactEmoticons = dic;
            }
            AppSettings.AppSettingsInstance.CustomEmoticons = AppSettings.AppSettingsInstance.CustomEmoticons;
            AppSettings.AppSettingsInstance.RecentlyUsedCustomEmoticons = AppSettings.AppSettingsInstance.RecentlyUsedCustomEmoticons;
            AppSettings.AppSettingsInstance.RecentlyUsedDefaultEmoticons = AppSettings.AppSettingsInstance.RecentlyUsedDefaultEmoticons;
        }

        // Code to execute if a navigation fails
        private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            if (Debugger.IsAttached)
            {
                // A navigation has failed; break into the debugger
                Debugger.Break();
            }
        }

        // Code to execute on Unhandled Exceptions
        private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {

            if (Debugger.IsAttached)
            {
                // An unhandled exception has occurred; break into the debugger
                Debugger.Break();
            }
        }

        #region Phone application initialization

        // Avoid double-initialization
        private bool phoneApplicationInitialized = false;

        // Do not add any additional code to this method
        private void InitializePhoneApplication()
        {
            if (phoneApplicationInitialized)
                return;

            // Create the frame but don't set it as RootVisual yet; this allows the splash
            // screen to remain active until the application is ready to render.
            var rootFrame = new TransitionFrame();//PhoneApplicationFrame();
            rootFrame.Background = StaticSettings.BackgroundBrush;
            RootFrame = rootFrame;
            RootFrame.Navigated += CompleteInitializePhoneApplication;

            // Handle navigation failures
            RootFrame.NavigationFailed += RootFrame_NavigationFailed;

            // Handle reset requests for clearing the backstack
            RootFrame.Navigated += CheckForResetNavigation;

            // Ensure we don't initialize again
            phoneApplicationInitialized = true;
        }

        // Do not add any additional code to this method
        private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
        {
            // Set the root visual to allow the application to render
            if (RootVisual != RootFrame)
                RootVisual = RootFrame;

            // Remove this handler since it is no longer needed
            RootFrame.Navigated -= CompleteInitializePhoneApplication;
        }

        private void CheckForResetNavigation(object sender, NavigationEventArgs e)
        {
            // If the app has received a 'reset' navigation, then we need to check
            // on the next navigation to see if the page stack should be reset
            if (e.NavigationMode == NavigationMode.Reset)
                RootFrame.Navigated += ClearBackStackAfterReset;
        }

        private void ClearBackStackAfterReset(object sender, NavigationEventArgs e)
        {
            // Unregister the event so it doesn't get called again
            RootFrame.Navigated -= ClearBackStackAfterReset;

            // Only clear the stack for 'new' (forward) and 'refresh' navigations
            if (e.NavigationMode != NavigationMode.New && e.NavigationMode != NavigationMode.Refresh)
                return;

            // For UI consistency, clear the entire page stack
            while (RootFrame.RemoveBackEntry() != null)
            {
                ; // do nothing
            }
        }

        #endregion

        // Initialize the app's font and flow direction as defined in its localized resource strings.
        //
        // To ensure that the font of your application is aligned with its supported languages and that the
        // FlowDirection for each of those languages follows its traditional direction, ResourceLanguage
        // and ResourceFlowDirection should be initialized in each resx file to match these values with that
        // file's culture. For example:
        //
        // AppResources.es-ES.resx
        //    ResourceLanguage's value should be "es-ES"
        //    ResourceFlowDirection's value should be "LeftToRight"
        //
        // AppResources.ar-SA.resx
        //     ResourceLanguage's value should be "ar-SA"
        //     ResourceFlowDirection's value should be "RightToLeft"
        //
        // For more info on localizing Windows Phone apps see http://go.microsoft.com/fwlink/?LinkId=262072.
        //
        private void InitializeLanguage()
        {
            try
            {
                // Set the font to match the display language defined by the
                // ResourceLanguage resource string for each supported language.
                //
                // Fall back to the font of the neutral language if the Display
                // language of the phone is not supported.
                //
                // If a compiler error is hit then ResourceLanguage is missing from
                // the resource file.
                RootFrame.Language = XmlLanguage.GetLanguage(AppResources.ResourceLanguage);

                // Set the FlowDirection of all elements under the root frame based
                // on the ResourceFlowDirection resource string for each
                // supported language.
                //
                // If a compiler error is hit then ResourceFlowDirection is missing from
                // the resource file.
                FlowDirection flow = (FlowDirection)Enum.Parse(typeof(FlowDirection), AppResources.ResourceFlowDirection);
                RootFrame.FlowDirection = flow;
            }
            catch
            {
                // If an exception is caught here it is most likely due to either
                // ResourceLangauge not being correctly set to a supported language
                // code or ResourceFlowDirection is set to a value other than LeftToRight
                // or RightToLeft.

                if (Debugger.IsAttached)
                {
                    Debugger.Break();
                }

                throw;
            }
        }
        public static void SetLockscreenState(bool isDisabled)
        {
            Microsoft.Phone.Shell.PhoneApplicationService.Current.UserIdleDetectionMode = isDisabled ? IdleDetectionMode.Disabled : IdleDetectionMode.Enabled;
        }
        public static void ResetTileCount()
        {
            App.unreadMsgCount = 0;
            App.UpdatePrimaryTile(App.unreadMsgCount);
            Connection.SendStatusMessage(MessageType.ResetUnreadMessageCount, StaticMethods.ObjectToString<DeviceInfo>(
                            new DeviceInfo
                            {
                                IsActive = true,
                                IsTileEnabled = AppSettings.AppSettingsInstance.IsTileNotificationEnabledSetting,
                                IsToastEnabled = AppSettings.AppSettingsInstance.IsToastNotificationEnabledSetting,
                                StoreMessagesWhileOffline = AppSettings.AppSettingsInstance.StoreMessagesWhileOfflineSetting,
                                OfflineMessagesAgeLimit = AppSettings.AppSettingsInstance.OfflineMessageAgeLimitSetting,
                                OfflineMessagesCountLimit = AppSettings.AppSettingsInstance.OfflineMessageCountLimitSetting
                            }));
        }
        public static void UpdatePrimaryTile(int count)
        {
            Uri smallIcon = null;
            if (count == 0)
                smallIcon = new Uri("/Assets/1xfeather-110x110px.png", UriKind.RelativeOrAbsolute);
            else
                smallIcon = new Uri("/Assets/1xfeather-70x110px.png", UriKind.RelativeOrAbsolute);
            Uri icon = null;
            if (count == 0)
                icon = new Uri("/Assets/1xfeather-202x202px.png", UriKind.RelativeOrAbsolute);
            else
                icon = new Uri("/Assets/1xfeather-130x202px.png", UriKind.RelativeOrAbsolute);
            IconicTileData primaryTileData = new IconicTileData();
            primaryTileData.Count = count;
            primaryTileData.SmallIconImage = smallIcon;
            primaryTileData.IconImage = icon;

            ShellTile primaryTile = ShellTile.ActiveTiles.First();
            RootFrame.Dispatcher.BeginInvoke(() =>
                {
                    primaryTile.Update(primaryTileData);
                });
        }
        private string GetUniqueId()
        {
            byte[] b = (byte[])DeviceExtendedProperties.GetValue("DeviceUniqueId");
            string str = Convert.ToBase64String(b);
            return "wp8" + str;
        }
        private void Application_RunningInBackground(object sender, RunningInBackgroundEventArgs e)
        {
            //RunningInBackground = true;

            //Debug.WriteLine(DateTime.Now.ToLongTimeString() + ": running in background = true");
        }
        public static void RegisterPush(bool enableTile, bool enableToast)
        {
            if (!Client.ClientInstance.IsLoggedIn)
                return;
            /// Holds the push channel that is created or found.
            HttpNotificationChannel pushChannel = null;

            // The name of our push channel.
            string channelName = "JivePushChannel";

            // Try to find the push channel.
            pushChannel = HttpNotificationChannel.Find(channelName);

            // If the channel was not found, then create a new connection to the push service.
            if (pushChannel == null)
            {
                // return;
                pushChannel = new HttpNotificationChannel(channelName);

                // Register for all the events before attempting to open the channel.
                pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(ToastPushChannel_ChannelUriUpdated);

                pushChannel.Open();

                pushChannel.BindToShellTile();

                pushChannel.BindToShellToast();

            }
            else
            {
                string uri = pushChannel.ChannelUri.ToString();
                Connection.SendStatusMessage(MessageType.PushUri, uri);

                if (!pushChannel.IsShellTileBound)
                    pushChannel.BindToShellTile();
                if (!pushChannel.IsShellToastBound)
                    pushChannel.BindToShellToast();
            }
        }

        void ToastPushChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
        {
            // Error handling logic for your particular application would be here.

            Messenger.Default.Send(String.Format("A push notification {0} error occurred.  {1} ({2}) {3}",
                e.ErrorType, e.Message, e.ErrorCode, e.ErrorAdditionalData));

        }
        private static void ToastPushChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
        {
            HttpNotificationChannel pushChannel = (HttpNotificationChannel)sender;
            Connection.SendStatusMessage(MessageType.PushUri, e.ChannelUri.ToString());
            pushChannel.ChannelUriUpdated -= new EventHandler<NotificationChannelUriEventArgs>(ToastPushChannel_ChannelUriUpdated);
        }
        void ToastPushChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
        {

        }


    }
}